package pers.lls.im.core.bootstrap;

import pers.lls.im.core.bootstrap.channel.HandlerServiceImpl;
import pers.lls.im.core.bootstrap.handler.DefaultHandler;
import pers.lls.im.core.common.bean.InitNetty;
import pers.lls.im.core.util.SslUtil;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;


/**
 * @author lihuan
 * @version V1.0 创建时间：2019/8/02
 * Copyright 2019 by landray & STIC
 */
@Slf4j
public abstract class AbstractBootstrapServer implements BootstrapServer {

    /**
     * @param channelPipeline channelPipeline
     */
    protected void initHandler(ChannelPipeline channelPipeline) {
        if (InitNetty.SSL) {
            if (!ObjectUtils.allNotNull(InitNetty.JKS_CERTIFICATE_PASSWORD, InitNetty.JKS_FILE, InitNetty.JKS_STORE_PASSWORD)) {
                throw new NullPointerException("SSL file and password is null");
            }
            try {
                SSLContext context = SslUtil.createSSLContext("JKS", InitNetty.JKS_FILE, InitNetty.JKS_STORE_PASSWORD);
                SSLEngine engine = context.createSSLEngine();
                engine.setUseClientMode(false);
                engine.setNeedClientAuth(false);
                channelPipeline.addLast("ssl", new SslHandler(engine));
            } catch (Exception e) {
                log.error(e.toString());
            }
        }
        intProtocolHandler(channelPipeline);
        channelPipeline.addLast(new IdleStateHandler(InitNetty.HEART, 0, 0));
        channelPipeline.addLast(new DefaultHandler(new HandlerServiceImpl()));
    }

    private void intProtocolHandler(ChannelPipeline channelPipeline) {
        channelPipeline.addLast("httpCode", new HttpServerCodec());
        channelPipeline.addLast("aggregator", new HttpObjectAggregator(InitNetty.MAX_CONTENT));
        channelPipeline.addLast("chunkedWrite", new ChunkedWriteHandler());
        channelPipeline.addLast("webSocketHandler", new WebSocketServerProtocolHandler(InitNetty.WEB_SOCKET_PATH));
    }


}
